home *** CD-ROM | disk | FTP | other *** search
/ Video Toaster 4.2 / Video Toaster v4.2.iso / programs / documentation / lightwave / sdk / sample / vsformat / vsformat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-20  |  7.1 KB  |  346 lines

  1. /*
  2.  * VSFORMAT.C -- LightWave Plugin Object Loader
  3.  *         Loads the old VideoScape format, text only
  4.  *
  5.  * written by Stuart Ferguson
  6.  * last revision  12/6/94
  7.  */
  8. #include <splug.h>
  9. #include <lwmod.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <math.h>
  13.  
  14.  
  15.  
  16. /*
  17.  * Read a two byte integer.  Returns true if the read was successful.
  18.  */
  19.     static int
  20. ReadShort (
  21.     FILE            *file,
  22.     short            *val)
  23. {
  24.     int             n, i;
  25.  
  26.     n = fscanf (file, "%d", &i);
  27.     *val = i;
  28.     return (n == 1);
  29. }
  30.  
  31.  
  32. /*
  33.  * Read a floating point format value.  Returns true if the read was
  34.  * successful.
  35.  */
  36.     static int
  37. ReadFloat (
  38.     FILE            *file,
  39.     float            *val)
  40. {
  41.     double             d;
  42.     int             n;
  43.  
  44.     n = fscanf (file, "%lf", &d);
  45.     *val = d;
  46.     return (n == 1);
  47. }
  48.  
  49.  
  50. /*
  51.  * For the surface number we look up the index and if this is the
  52.  * first time the surface is added, we set the parameters.
  53.  */
  54.     static int
  55. SurfIndexFromColor (
  56.     ObjectImport        *local,
  57.     int             color)
  58. {
  59.     unsigned char        *dp;
  60.     int             isurf, on, first;
  61.     static char         name[28], buf[64];
  62.  
  63.     sprintf (name, "VideoScape Color %d", color);
  64.     isurf = (*local->surfIndex) (local->data, name, &first);
  65.  
  66.     if (!first || color >= 256)
  67.         return isurf;
  68.  
  69.     /*
  70.      * A surface parameter block is just what we would expect
  71.      * to find in a SURF chunk, minus the surface name.  This
  72.      * macro inserts a small color chunk header on the buffer.
  73.      */
  74.     dp = buf;
  75. #define SURF_HDR(p,a,b,c,d,n)    p[0]=a; p[1]=b; p[2]=c; p[3]=d;\
  76.                 p[4]=0; p[5]=n; p+=6;
  77.  
  78.     /*
  79.      * The COLR chunk contains a crude RGB based on the low
  80.      * 4 bits of the color number.
  81.      */
  82.     SURF_HDR (dp, 'C','O','L','R', 4);
  83.     on = (color & 8 ? 240 : 140);
  84.     *dp++ = (color & 4 ? on : 0);
  85.     *dp++ = (color & 2 ? on : 0);
  86.     *dp++ = (color & 1 ? on : 0);
  87.     *dp++ = 0;
  88.  
  89.     /*
  90.      * The FLAG chunk contains a bit for smoothing if the
  91.      * smoothing bit is set in the color number.
  92.      */
  93.     SURF_HDR (dp, 'F','L','A','G', 2);
  94.     *dp++ = 0;
  95.     *dp++ = (color & 128 ? (1<<2) : 0);
  96.  
  97.     /*
  98.      * The DIFF chunk contains a diffuse value of 255 for non-
  99.      * luminous surfaces, or 0 if luminous.
  100.      */
  101.     SURF_HDR (dp, 'D','I','F','F', 2);
  102.     *dp++ = 0;
  103.     *dp++ = (color & 32 ? 0 : 255);
  104.  
  105.     /*
  106.      * If the color is luminous and diffuse is zero, we need
  107.      * a luminous sub-chunk with a 255 (100%) setting.
  108.      */
  109.     if (color & 32) {
  110.         SURF_HDR (dp, 'L','U','M','I', 2);
  111.         *dp++ = 0;
  112.         *dp++ = 255;
  113.     }
  114.  
  115.     /*
  116.      * If the transparent bit is set, the TRAN chunk will have
  117.      * a 50% transparency value.
  118.      */
  119.     if (color & 64) {
  120.         SURF_HDR (dp, 'T','R','A','N', 2);
  121.         *dp++ = 0;
  122.         *dp++ = 127;
  123.     }
  124.  
  125.     /*
  126.      * If the glossy bit is set, the color will have a specular
  127.      * setting of 255 and glossiness of 64.
  128.      */
  129.     if (color & 64) {
  130.         SURF_HDR (dp, 'S','P','E','C', 2);
  131.         *dp++ = 0;
  132.         *dp++ = 255;
  133.  
  134.         SURF_HDR (dp, 'G','L','O','S', 2);
  135.         *dp++ = 0;
  136.         *dp++ = 64;
  137.     }
  138.  
  139.     (*local->surfData) (local->data, name, (int)(dp - buf), buf);
  140.     return isurf;
  141. }
  142.  
  143.  
  144. /*
  145.  * Read a polygon description from file.  Returns zero if this was the last
  146.  * polygon detected, or if there was an error in which case the result
  147.  * field will be set.
  148.  */
  149.     static int
  150. ReadPolygon (
  151.     ObjectImport        *local,
  152.     FILE            *file,
  153.     int             isDetail)
  154. {
  155.     short             color, nvert, numDet;
  156.     int             hasDetails, i, isurf, flags;
  157.     static unsigned short     verts[200];
  158.     const char        *errmsg = NULL;
  159.  
  160.     /*
  161.      * Read number of vertices in the next polygon.  Deal with end of
  162.      * file and other cases.
  163.      */
  164.     if (!ReadShort (file, &nvert))
  165.         return 0;
  166.  
  167.     if (!nvert)
  168.         return 0;
  169.  
  170.     if (nvert > 200) {
  171.         errmsg = "Geo format: Polygon too large";
  172.         goto failed;
  173.     }
  174.  
  175.     /*
  176.      * Read polygon vertex list given by number of vertices expected
  177.      * as indicies into the already read vertex list.
  178.      */
  179.     for (i = 0; i < nvert; i++)
  180.         if (!ReadShort (file, (short *) &verts[i]))
  181.             goto failed;
  182.  
  183.     /*
  184.      * Next value must be VideoScape surface number.
  185.      */
  186.     if (!ReadShort (file, &color))
  187.         goto failed;
  188.  
  189.     /*
  190.      * If negative, this polygon has some detail polygons.
  191.      */
  192.     hasDetails = (color < 0);
  193.     if (hasDetails)
  194.         color = -color;
  195.  
  196.     /*
  197.      * Create the polygon given the number of vertices, the vertex list
  198.      * as point indices, the flags (a face which might be a detail) and
  199.      * the surface index from above.
  200.      */
  201.     isurf = SurfIndexFromColor (local, color);
  202.     flags = OBJPOLF_FACE | (isDetail ? OBJPOLF_DETAIL : 0);
  203.     (*local->polygon) (local->data, nvert, isurf, flags, verts);
  204.  
  205.     /*
  206.      * If there are no details, this polygon is read successfully.
  207.      */
  208.     if (!hasDetails)
  209.         return 1;
  210.  
  211.     /*
  212.      * Read the details recursively for the given number of polygon.
  213.      */
  214.     if (isDetail || !ReadShort (file, &numDet))
  215.         goto failed;
  216.  
  217.     for (i = 0; i < numDet; i++)
  218.         if (!ReadPolygon (local, file, 1))
  219.             goto failed;
  220.  
  221.     return 1;
  222.  
  223.  failed:
  224.     local->result = OBJSTAT_FAILED;
  225.     if (!errmsg)
  226.         errmsg = "Geo format: EOF in polygon definition";
  227.     if (local->failedLen > 0)
  228.         strncpy (local->failedBuf, errmsg, local->failedLen);
  229.  
  230.     return 0;
  231. }
  232.  
  233.  
  234. /*
  235.  * Object file loading entry point.  We get a filename and have the option
  236.  * of attempting to load it or passing on it altogether.
  237.  */
  238.     XCALL_(int)
  239. Activate (
  240.     long             version,
  241.     GlobalFunc        *global,
  242.     ObjectImport        *local,
  243.     void            *serverData)
  244. {
  245.     FILE            *file;
  246.     float             pos[3];
  247.     char             str[6];
  248.     short             npts;
  249.     int             i, ok;
  250.     const char        *errmsg;
  251.  
  252.     /*
  253.      * Check interface version.
  254.      */
  255.     XCALL_INIT;
  256.     if (version != 1)
  257.         return AFUNC_BADVERSION;
  258.  
  259.     /*
  260.      * Open the file for read, text mode.  If it fails, we exit with
  261.      * a BADFILE result.
  262.      */
  263.     file = fopen (local->filename, "r");
  264.     if (!file) {
  265.         local->result = OBJSTAT_BADFILE;
  266.         return AFUNC_OK;
  267.     }
  268.  
  269.     /*
  270.      * Test sync pattern.  If we don't get what we expect, we exit
  271.      * with a NOREC result.
  272.      */
  273.     fread (str, (size_t)1, (size_t)4, file);
  274.     if (strncmp (str, "3DG1", (size_t)4)) {
  275.         local->result = OBJSTAT_NOREC;
  276.         fclose (file);
  277.         return AFUNC_OK;
  278.     }
  279.  
  280.     /*
  281.      * Read number of points which must be non-zero.
  282.      */
  283.     if (!ReadShort (file, &npts) || !npts) {
  284.         errmsg = "Geo format: No point count";
  285.         goto failed;
  286.     }
  287.  
  288.     /*
  289.      * Begin sending object data by sending number of points.  Result
  290.      * code will be left alone unless there is a read failure.
  291.      */
  292.     local->result = OBJSTAT_OK;
  293.     (*local->begin) (local->data, NULL);
  294.     (*local->numPoints) (local->data, (int)npts);
  295.  
  296.     /*
  297.      * Read all the points one number at a time.
  298.      */
  299.     for (i = 0; i < npts; i++) {
  300.         ok  = ReadFloat (file, &pos[0]);
  301.         ok &= ReadFloat (file, &pos[1]);
  302.         ok &= ReadFloat (file, &pos[2]);
  303.         if (!ok) {
  304.             errmsg = "Geo format: Not enough points";
  305.             goto failed;
  306.         }
  307.  
  308.         (*local->points) (local->data, 1, pos);
  309.     }
  310.  
  311.     /*
  312.      * Scan polygons until ReadPolygon returns False, which signals the
  313.      * end of file or an error in which case the result value is set.
  314.      */
  315.     while (ReadPolygon (local, file, 0))
  316.         ;
  317.  
  318.     /*
  319.      * Normal exit.  The `done' callback is called to end sending data
  320.      * to the host and the file is closed.
  321.      */
  322.     (*local->done) (local->data);
  323.     fclose (file);
  324.     return AFUNC_OK;
  325.  
  326.  
  327.     /*
  328.      * Abnormal exit.  This sets the result code to failure and closes
  329.      * the file and exits.
  330.      */
  331.  failed:
  332.     fclose (file);
  333.     local->result = OBJSTAT_FAILED;
  334.     if (errmsg && local->failedLen > 0)
  335.         strncpy (local->failedBuf, errmsg, local->failedLen);
  336.  
  337.     return AFUNC_OK;
  338. }
  339.  
  340.  
  341. /*
  342.  * Globals necessary to declare the class and name of this plugin server.
  343.  */
  344. char        ServerClass[] = "ObjectLoader";
  345. char        ServerName[]  = "Demo_3DG1";
  346.